package su.camunda.operate.process;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.history.HistoricVariableInstance;
import org.camunda.bpm.engine.history.HistoricVariableInstanceQuery;
import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import lombok.AllArgsConstructor;
import su.camunda.operate.dto.PassTaskDto;
import su.camunda.operate.dto.SetProcessVarDto;
import su.camunda.operate.dto.StartProcessDto;
import su.camunda.operate.result.FlwProcessVariableResult;
import su.camunda.operate.result.TaskDetail;

@RestController
@AllArgsConstructor
public class TaskController {

    private static final String success = "success";
    private final ProcessEngine processEngine;

    /**
     * 启动流程实例
     */
    @PostMapping(value = "/startProcessInstance")
    public String startProcessInstance(@RequestBody StartProcessDto startProcessDto) {
        ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(startProcessDto.getProcessDefinitionKey(), startProcessDto.getVariables());
        return processInstance.getProcessInstanceId();
    }

    /**
     * 查询当前流程实例下所有的任务
     */
    @GetMapping("/getTasksByProcessInstanceId")
    public List<TaskDetail> getTasksByProcessInstanceId(@RequestParam String processInstanceId) {
        return processEngine.getTaskService().createTaskQuery().processInstanceId(processInstanceId).list().stream().map(task -> (TaskEntity) task).map(item -> new TaskDetail(item.getAssignee(), item.getId(), item.getExecutionId(), item.getProcessInstanceId(), item.getName())).collect(Collectors.toList());
    }

    /**
     * 完成任务
     */
    @PostMapping("/completeTask")
    public void completeTask(@RequestBody PassTaskDto passTaskDto) {
        Map<String, Object> taskPassMap = passTaskDto.getTaskPassMap();
        if (CollUtil.isNotEmpty(taskPassMap)) {
            processEngine.getTaskService().complete(passTaskDto.getTaskId(), taskPassMap);
        } else {
            processEngine.getTaskService().complete(passTaskDto.getTaskId());
        }
    }


    /**
     * 设置任务本地变量
     */
    @PostMapping("/setTaskVariableLocal")
    public String setTaskVariableLocal(@RequestBody SetProcessVarDto setProcessVarDto) {
        Map<String, Object> taskPassMap = setProcessVarDto.getTaskPassMap();
        if (CollUtil.isNotEmpty(taskPassMap)) {
            processEngine.getTaskService().setVariablesLocal(setProcessVarDto.getExecutionId(), taskPassMap);
            return success;
        }
        return null;
    }


    /**
     * 设置任务本地变量
     */
    @PostMapping("/setTaskVariableLocalAndSubmit")
    public void setTaskVariableLocalAndSubmit(@RequestBody SetProcessVarDto setProcessVarDto) {
        Map<String, Object> taskPassMap = setProcessVarDto.getTaskPassMap();
        if (CollUtil.isNotEmpty(taskPassMap)) {
            processEngine.getTaskService().setVariablesLocal(setProcessVarDto.getExecutionId(), taskPassMap);
            processEngine.getTaskService().complete(setProcessVarDto.getExecutionId());
            return;
        }
        processEngine.getTaskService().complete(setProcessVarDto.getExecutionId());
    }


    /**
     * 设置流程变量
     */
    @PostMapping("/setProcessVariable")
    public String setProcessVariable(@RequestBody SetProcessVarDto setProcessVarDto) {
        Map<String, Object> taskPassMap = setProcessVarDto.getTaskPassMap();
        if (CollUtil.isNotEmpty(taskPassMap)) {
            processEngine.getRuntimeService().setVariables(setProcessVarDto.getExecutionId(), taskPassMap);
            return success;
        }
        return null;
    }

    /**
     * 设置本地变量
     */
    @PostMapping("/setVariableLocal")
    public String setVariableLocal(@RequestBody SetProcessVarDto setProcessVarDto) {
        Map<String, Object> taskPassMap = setProcessVarDto.getTaskPassMap();
        if (CollUtil.isNotEmpty(taskPassMap)) {
            processEngine.getRuntimeService().setVariablesLocal(setProcessVarDto.getExecutionId(), taskPassMap);
            return success;
        }
        return null;
    }

    /**
     * 查询流程变量
     */
    @GetMapping("/getProcessVariable")
    public Object getProcessVariable(@RequestParam String executionId, @RequestParam String variableName) {
        HistoricVariableInstance historicVariableInstance = processEngine.getHistoryService().createHistoricVariableInstanceQuery().executionIdIn(executionId).variableName(variableName).singleResult();
        if (Objects.isNull(historicVariableInstance)) {
            return "not find value";
        }
        return historicVariableInstance.getValue();
    }

    /**
     * 查询所有的流程变量
     */
    @GetMapping("/variablePage")
    public List<FlwProcessVariableResult> variablePage(@RequestParam String executionId) {
        HistoricVariableInstanceQuery historicVariableInstanceQuery = processEngine.getHistoryService().createHistoricVariableInstanceQuery().processInstanceId(executionId).orderByVariableName().desc();
        List<FlwProcessVariableResult> flwProcessVariableResultList = historicVariableInstanceQuery.list().stream().map(historicVariableInstance -> {
            FlwProcessVariableResult flwProcessVariableResult = new FlwProcessVariableResult();
            flwProcessVariableResult.setId(historicVariableInstance.getId());
            flwProcessVariableResult.setProcessInstanceId(historicVariableInstance.getProcessInstanceId());
            flwProcessVariableResult.setExecutionId(historicVariableInstance.getExecutionId());
            flwProcessVariableResult.setTypeName(historicVariableInstance.getTypeName());
            flwProcessVariableResult.setName(historicVariableInstance.getName());
            String taskId = historicVariableInstance.getTaskId();
            flwProcessVariableResult.setFlwTaskId(taskId);
            flwProcessVariableResult.setValue(Convert.toStr(historicVariableInstance.getValue()));
            return flwProcessVariableResult;
        }).collect(Collectors.toList());
        return flwProcessVariableResultList;
    }


}
